package com.example.budget3.months.graphs;

import java.util.ArrayList;

import com.example.budget3.util.UtilMethods;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Path.Direction;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.Region;
import android.util.AttributeSet;
import android.view.View;

public class LineGraph extends View {
	
	private ArrayList<Line> lines = new ArrayList<Line>();
	Paint paint = new Paint();
	private float minX = 0;
	private float maxY = 0, maxX = 0;
	private boolean isMaxYUserSet = false;
	private boolean isMinYUserSet = false;
	private boolean isMaxXUserSet = false;
	private boolean isMinXUserSet = false;
	private int lineToFill = -1;
	private Bitmap fullImage;
	private boolean shouldUpdate = false;
	private boolean allZero = false;
	private Context context;
	
	public void setAllZero(boolean allZero) {
		this.allZero = allZero;
	}

	public LineGraph(Context context){
		super(context);
		this.context = context;
	}
	
	public LineGraph(Context context, AttributeSet attrs) {
		super(context, attrs);
		this.context = context;
	}
	
	public void removeAllLines(){
		while (lines.size() > 0){
			lines.remove(0);
		}
		shouldUpdate = true;
		postInvalidate();
	}
	
	public void setSelectedLineAndPoint(int selectedPoint, int selectedLine){
		
		this.lineToFill = selectedLine;
	}
	
	public void addLine(Line line) {
		lines.add(line);
		shouldUpdate = true;
		postInvalidate();
	}
	public ArrayList<Line> getLines() {
		return lines;
	}
	public void setLineToFill(int indexOfLine) {
		this.lineToFill = indexOfLine;
		shouldUpdate = true;
		postInvalidate();
	}
	public int getLineToFill(){
		return lineToFill;
	}
	public void setLines(ArrayList<Line> lines) {
		this.lines = lines;
	}
	public Line getLine(int index) {
		return lines.get(index);
	}
	public int getSize(){
		return lines.size();
	}
	
	public void setRangeY(float min, float max) {
		maxY = max;
		isMaxYUserSet = true;
		isMinYUserSet = true;
	}
	
	public void setRangeX(float min, float max) {
		minX = min;
		maxX = max;
		isMaxXUserSet = true;
		isMinXUserSet = true;
	}
	
	public float getMaxY(){
		if (isMaxYUserSet){
			return maxY;
		} else {
			float max = lines.get(0).getPoint(0).getY();
			for (Line line : lines){
				for (LinePoint point : line.getPoints()){
					if (point.getY() > max){
						max = point.getY();
					}
				}
			}
			return maxY = max;
		}
		
	}
	public float getMinY(){
		if (isMinYUserSet){
			return 0;
		} else {
			float min = lines.get(0).getPoint(0).getY();
			for (Line line : lines){
				for (LinePoint point : line.getPoints()){
					if (point.getY() < min) min = point.getY();
				}
			}

			return 0;
		}
	}
	public float getMaxX(){
		if (isMaxXUserSet){
			return maxX;
		}
		float max = lines.get(0).getPoint(0).getX();
		for (Line line : lines){
			for (LinePoint point : line.getPoints()){
				if (point.getX() > max) max = point.getX();
			}
		}
		maxX = max;
		return maxX;
		
	}
	public float getMinX(){
		if (isMinXUserSet){
			return minX;
		}
		
		float min = lines.get(0).getPoint(0).getX();
		for (Line line : lines){
			for (LinePoint point : line.getPoints()){
				if (point.getX() < min) min = point.getX();
			}
		}
		minX = min;
		return minX;
	}
	
	@SuppressLint({ "DrawAllocation", "DefaultLocale" })
	public void onDraw(Canvas ca) {
		if (fullImage == null || shouldUpdate) {
			fullImage = Bitmap.createBitmap(getWidth(), getHeight(), Config.ARGB_8888);
			Canvas canvas = new Canvas(fullImage);
			
			paint.reset();
			Path path = new Path();
			
			float bottomPadding = 10;
			float sidePadding = 10;
			float padding = 7;
			this.paint.setTextSize(40);
			Rect r3 = new Rect();
			String currency = UtilMethods.getCurrency(context);
			this.paint.getTextBounds(currency, 0, 1, r3);
			float usableHeight = (((getHeight()-r3.height())-15)-bottomPadding)-(2*padding);
			
			
			float usableWidth = getWidth() - 2*sidePadding;
			
	
			int lineCount = 0;
			for (Line line : lines){
				int count = 0;
				float lastXPixels = 0, newYPixels = 0;
				float lastYPixels = 0, newXPixels = 0;
				float maxY = getMaxY();
				float minY = getMinY();
				float maxX = getMaxX();
				float minX = getMinX();
				
				if (lineCount == lineToFill){
					paint.setColor(line.getColor());
					for (int i = 10; i-getWidth() < getHeight(); i = i+20){
						canvas.drawLine(i, getHeight()-bottomPadding, 0, getHeight()-bottomPadding-i, paint);
					}
					
					paint.reset();
					
					paint.setXfermode(new PorterDuffXfermode(android.graphics.PorterDuff.Mode.CLEAR));
					
					
					float yPercent1 = 0;
					float xPercent1 = (minX)/(maxX - minX);
					
					lastXPixels = sidePadding + (xPercent1*usableWidth);
					lastYPixels = getHeight() - bottomPadding - (usableHeight*yPercent1);
					path.moveTo(lastXPixels, lastYPixels);
					
					float yPercent2 = 0;
					float xPercent2 = (line.getPoints().get(0).getX()-minX)/(maxX - minX);
					
					newXPixels = sidePadding + (xPercent2*usableWidth);
					newYPixels = getHeight() - bottomPadding - (usableHeight*yPercent2);
					path.lineTo(newXPixels, newYPixels);
					Path pa = new Path();
					pa.moveTo(lastXPixels, lastYPixels);
					pa.lineTo(newXPixels, newYPixels);
					pa.lineTo(newXPixels, 0);
					pa.lineTo(lastXPixels, 0);
					pa.close();
					canvas.drawPath(pa, paint);
					lastXPixels = newXPixels;
					lastYPixels = newYPixels;

			
					for (LinePoint p : line.getPoints()){
						float yPercent;
						if(allZero){
							yPercent = (p.getY()-minY)/(10 - minY);
						}else{
							yPercent = (p.getY()-minY)/(maxY - minY);
						}
						float xPercent = (p.getX()-minX)/(maxX - minX);
						if (count == 0){
							lastXPixels = sidePadding + (xPercent*usableWidth);
							lastYPixels = getHeight() - bottomPadding - (usableHeight*yPercent);
							path.moveTo(lastXPixels, lastYPixels);
						} else {
							newXPixels = sidePadding + (xPercent*usableWidth);
							newYPixels = getHeight() - bottomPadding - (usableHeight*yPercent);
							path.lineTo(newXPixels, newYPixels);
	
							pa.moveTo(lastXPixels, lastYPixels);
							pa.lineTo(newXPixels, newYPixels);
							pa.lineTo(newXPixels, 0);
							pa.lineTo(lastXPixels, 0);
							pa.close();
							canvas.drawPath(pa, paint);
							lastXPixels = newXPixels;
							lastYPixels = newYPixels;
						}
						count++;
					}
					
					float yPercent3 = 0;
					float xPercent3 = (line.getPoints().get(line.getSize()-1).getX()-minX)/(maxX - minX);
					
					lastXPixels = sidePadding + (xPercent3*usableWidth);
					lastYPixels = getHeight() - bottomPadding - (usableHeight*yPercent3);
					path.moveTo(lastXPixels, lastYPixels);
					
					float yPercent4 = 0;
					float xPercent4 = (maxX-minX)/(maxX - minX);
					
					newXPixels = sidePadding + (xPercent4*usableWidth);
					newYPixels = getHeight() - bottomPadding - (usableHeight*yPercent4);
					path.lineTo(newXPixels, newYPixels);
					pa.moveTo(lastXPixels, lastYPixels);
					pa.lineTo(newXPixels, newYPixels);
					pa.lineTo(newXPixels, 0);
					pa.lineTo(lastXPixels, 0);
					pa.close();
					canvas.drawPath(pa, paint);
					lastXPixels = newXPixels;
					lastYPixels = newYPixels;
					
					
					
					
					path.reset();
					
					path.moveTo(0, getHeight()-bottomPadding);
					path.lineTo(sidePadding, getHeight()-bottomPadding);
					path.lineTo(sidePadding, 0);
					path.lineTo(0, 0);
					path.close();
					canvas.drawPath(path, paint);
					
					path.reset();
					
					path.moveTo(getWidth(), getHeight()-bottomPadding);
					path.lineTo(getWidth()-sidePadding, getHeight()-bottomPadding);
					path.lineTo(getWidth()-sidePadding, 0);
					path.lineTo(getWidth(), 0);
					path.close();
					
					canvas.drawPath(path, paint);
					
				}
				
				lineCount++;
			}
			
			paint.reset();


			paint.setAntiAlias(true);		
			
			for (Line line : lines){
				int count = 0;
				float lastXPixels = 0, newYPixels = 0;
				float lastYPixels = 0, newXPixels = 0;
				float maxY = getMaxY();
				float minY = getMinY();
				float maxX = getMaxX();
				float minX = getMinX();
				
				paint.setColor(line.getColor());
				paint.setStrokeWidth(6);
				
				for (LinePoint p : line.getPoints()){
					float yPercent;
					if(allZero){
						yPercent = (p.getY()-minY)/(10 - minY);
					}else{
						yPercent = (p.getY()-minY)/(maxY - minY);
					}
					
					float xPercent = (p.getX()-minX)/(maxX - minX);
					if (count == 0){
						lastXPixels = sidePadding + (xPercent*usableWidth);
						lastYPixels = getHeight() - bottomPadding - (usableHeight*yPercent);
					} else {
						newXPixels = sidePadding + (xPercent*usableWidth);
						newYPixels = getHeight() - bottomPadding - (usableHeight*yPercent);
						canvas.drawLine(lastXPixels, lastYPixels, newXPixels, newYPixels, paint);
						lastXPixels = newXPixels;
						lastYPixels = newYPixels;
					}
					count++;
				}
			}
			
			
			for (Line line : lines){
				float maxY = getMaxY();
				float minY = getMinY();
				float maxX = getMaxX();
				float minX = getMinX();
				
				paint.setColor(line.getColor());
				paint.setStrokeWidth(6);
				paint.setStrokeCap(Paint.Cap.ROUND);
				
				if (line.isShowingPoints()){
					for (LinePoint p : line.getPoints()){
						float yPercent;
						if(allZero){
							yPercent = (p.getY()-minY)/(10 - minY);
						}else{
							yPercent = (p.getY()-minY)/(maxY - minY);
						}
						float xPercent = (p.getX()-minX)/(maxX - minX);
						float xPixels = sidePadding + (xPercent*usableWidth);
						float yPixels = getHeight() - bottomPadding - (usableHeight*yPercent);
						
						paint.setColor(line.getColor());
						canvas.drawCircle(xPixels, yPixels, 2, paint);
						
						
						Path path2 = new Path();
						path2.addCircle(xPixels, yPixels, 30, Direction.CW);
						p.setPath(path2);
						p.setRegion(new Region((int)(xPixels-30), (int)(yPixels-30), (int)(xPixels+30), (int)(yPixels+30)));
						
					}
				}
			}
			
			shouldUpdate = false;

		}

		ca.drawBitmap(fullImage, 0, 0, null);

	}

}
